-----------------
-- Addon Setup --
-----------------
local ECSNAME = "Enhanced Character Statistics"

local ecs = LibStub("AceAddon-3.0"):GetAddon(ECSNAME)
local ecsVersion = GetAddOnMetadata(ECSNAME, "Version")

local L			= LibStub("AceLocale-3.0"):GetLocale(ECSNAME)
local AceConfig		= LibStub("AceConfig-3.0")
local AceConfigReg	= LibStub("AceConfigRegistry-3.0")
local AceConfigDialog	= LibStub("AceConfigDialog-3.0")

local db = {}
local modularOptions = {}

--Set Up Faction options. Hidden = True
local pFaction = UnitFactionGroup("player")
local alliance, horde = true, true
if pFaction == "Alliance" then alliance = false end
if pFaction == "Horde" then horde = false end
--Set UP Power options. Hidden = True
local pPower = UnitPowerType("player")
local mana, rage, energy, runic = true, true, true, true
if pPower == 3 then energy = false end
if pPower == 6 then runic = false end
if pPower == 0 then mana = false end
if pPower == 1 then rage = false end
--Set Up Class options. Hidden = True
local _, pClass = UnitClass("player")
local paladin, priest, warlock = true, true, true
local warrior, hunter, shaman = true, true, true
local rogue, mage, deathknight, druid = true, true, true, true
if pClass == "DEATHKNIGHT" then deathknight = false end
if pClass == "WARRRIOR" then warrior = false end
if pClass == "PALADIN" then paladin = false end
if pClass == "WARLOCK" then warlock = false end
if pClass == "PRIEST" then priest = false end
if pClass == "SHAMAN" then shaman = false end
if pClass == "DRUID" then druid = false end
if pClass == "ROGUE" then rogue = false end
if pClass == "MAGE" then mage = false end

-------------------------
-- Localized Constants --
-------------------------
local STRENGTH = SPELL_STAT1_NAME
local AGILITY = SPELL_STAT2_NAME
local STAMINA = SPELL_STAT3_NAME
local INTELLECT = SPELL_STAT4_NAME
local SPIRIT = SPELL_STAT5_NAME
local ARMOR = ARMOR
local ATTACK_POWER = ATTACK_POWER_TOOLTIP
local MANA_REGEN = MANA_REGEN
local HIT_RATING = COMBAT_RATING_NAME6

local MELEE = PLAYERSTAT_MELEE_COMBAT
local RANGE = PLAYERSTAT_RANGED_COMBAT
local SPELL = PLAYERSTAT_SPELL_COMBAT
-------------------
-- Getter Setter --
-------------------
local function getter(info)
	local opt,arg = strsplit(".", info.arg);
	if (arg) then
		return db[opt][arg];
	else
		return db[opt];
	end
end

local function setter(info, val)
	local opt,arg = strsplit(".", info.arg);
	if (arg) then
		db[opt][arg] = val;
	else
		db[opt] = val;
	end
end

-------------------
-- Options Menus --
-------------------
local options = nil
local function fullOptions()

	if (not options) then
		options = {
			type = "group",
			name = ECSNAME,
			get = getter,
			set = setter,
			args = {
				general = {
					order	= 1,
					type	= "group",
					name	= L["STATS"],
					desc	= L["STATS_DESC"],
					args	= {
						statsEnable = {
							order	= 10,
							type	= "toggle",
							name	= L["GENERAL_SHOWSTATS"],
							arg	= "general.showStats",
							width	= "full",
						},
						meleeHitEnable = {
							order	= 11,
							type	= "toggle",
							name	= L["GENERAL_SHOWMELEEHIT"],
							arg	= "general.meleeHit",
							width	= "full",
						},
						--[[
						rangeHitEnable = {
							order	= 12,
							type	= "toggle",
							name	= L["GENERAL_SHOWRANGEHIT"],
							arg	= "general.rangeHit",
							width	= "full",
						},
						]]
						spellHitEnable = {
							order	= 13,
							type	= "toggle",
							name	= L["GENERAL_SHOWSPELLHIT"],
							arg	= "general.spellHit",
							width	= "full",
						},
						statsEmptySpace = {
							order	= 13,
							type	= "toggle",
							name	= L["GENERAL_EMPTYSPACE"],
							desc	= L["GENERAL_EMPTYSPACE_DESC"],
							arg	= "general.emptySpace",
							width	= "full",
						},
					},
				},
			},
		}

		for k,v in pairs(modularOptions) do
			options.args[k] = (type(v) == "function") and v() or v;
		end
	end
	return options;
end

------------------
-- Stats Module -- 
------------------
local stats = nil
local function giveStats()

	if (not stats) then
		stats = {
			type = "group",
			name = ECSNAME,
			get = getter,
			set = setter,
			args = {
				strHeader = {
					order	= 11,
					type	= "header",
					name	= STRENGTH,
					hidden	= deathknight,
				},
				strCRParry = {
					order	= 12,
					type	= "toggle",
					name	= L["Show Parry"],
					desc	= L["ADD_CR_PARRY_MOD_STR"],
					arg	= "GetModList.ADD_CR_PARRY_MOD_STR",
					hidden	= deathknight,
				},
				agiHeader = {
					order	= 21,
					type	= "header",
					name	= AGILITY,
				},
				agiDodge = {
					order	= 22,
					type	= "toggle",
					name	= L["Show Dodge"],
					desc	= L["ADD_DODGE"],
					arg	= "stats.dodge",
				},
				agiHealing = {
					order	= 23,
					type	= "toggle",
					name	= L["Show Healing"],
					desc	= L["ADD_HEALING_MOD_AGI"],
					arg	= "GetModList.ADD_HEALING_MOD_AGI",
					hidden	= druid,
				},
				staHeader = {
					order	= 31,
					type	= "header",
					name	= STAMINA,
					hidden	= paladin and hunter and warlock,
				},
				staAttackPower = {
					order	= 33,
					type	= "toggle",
					name	= L["Show Attack Power"],
					desc	= L["ADD_AP_MOD_STA"],
					arg	= "GetModList.ADD_AP_MOD_STA",
					hidden	= hunter,
				},
				staSpellPower = {
					order	= 34,
					type	= "toggle",
					name	= L["Show Spellpower"],
					desc	= L["ADD_SPELL_DMG_MOD_STA"],
					arg	= "GetModList.ADD_SPELL_DMG_MOD_STA",
					hidden	= paladin and warlock,
				},
				intHeader = {
					order	= 41,
					type	= "header",
					name	= INTELLECT,
					hidden	= mage and shaman and paladin and druid and warlock and hunter,
				},
				intHealing = {
					order	= 42,
					type	= "toggle",
					name	= L["Show Healing"],
					desc	= L["ADD_HEALING_MOD_INT"],
					arg	= "GetModList.ADD_HEALING_MOD_INT",
					hidden	= shaman,
				},
				intAttackPower = {
					order	= 43,
					type	= "toggle",
					name	= L["Show Attack Power"],
					desc	= L["ADD_AP_MOD_INT"],
					arg	= "GetModList.ADD_AP_MOD_INT",
					hidden	= shaman,
				},
				intManaRegen = {
					order	= 44,
					type	= "toggle",
					name	= L["Show Mana Regen"],
					desc	= L["ADD_MANA_REG_MOD_INT"],
					arg	= "GetModList.ADD_MANA_REG_MOD_INT",
					hidden	= druid and shaman, 
				},
				intRangedAP = {
					order	= 45,
					type	= "toggle",
					name	= L["Show Ranged Attack Power"],
					desc	= L["ADD_RANGED_AP_MOD_INT"],
					arg	= "GetModList.ADD_RANGED_AP_MOD_INT",
					hidden	= hunter,
				},
				intArmor = {
					order	= 46,
					type	= "toggle",
					name	= L["Show Armor"],
					desc	= L["ADD_ARMOR_MOD_INT"],
					arg	= "GetModList.ADD_ARMOR_MOD_INT",
					hidden	= mage,
				},
				intSpellPower = {
					order	= 47,
					type	= "toggle",
					name	= L["Show Spellpower"],
					desc	= L["ADD_SPELL_DMG_MOD_INT"],
					arg	= "GetModList.ADD_SPELL_DMG_MOD_INT",
					hidden	= druid and mage and warlock and paladin,
				},
				intReplenish = {
					order	= 48,
					type	= "toggle",
					name	= L["Show Replenish"],
					desc	= "REPLENISH_INT_DESC",
					arg	= "stats.intreplenish",
					hidden	= mana,
				},
				spiHeader = {
					order	= 51,
					type	= "header",
					name	= SPIRIT,
					hidden	= druid and priest and warlock and mage,
				},
				spiHealing = {
					order	= 52,
					type	= "toggle",
					name	= L["Show Healing"],
					desc	= L["ADD_HEALING_MOD_SPI"],
					arg	= "GetModList.ADD_HEALING_MOD_SPI",
					hidden	= druid,
				},
				spiSpellPower = {
					order	= 53,
					type	= "toggle",
					name	= L["Show Spellpower"],
					desc	= L["ADD_SPELL_DMG_MOD_SPI"],
					arg	= "GetModList.ADD_SPELL_DMG_MOD_SPI",
					hidden	= priest and druid and warlock,
				},
				spiSpellCrit = {
					order	= 54,
					type	= "toggle",
					name	= L["Show Spell Critical"],
					desc	= L["ADD_SPELL_CRIT_RATING_MOD_SPI"],
					arg	= "GetModList.ADD_SPELL_CRIT_RATING_MOD_SPI",
					hidden	= mage,
				},
				apHeader = {
					order	= 61,
					type	= "header",
					name	= ATTACK_POWER,
					hidden	= paladin and shaman,
				},
				apSpellPower = {
					order	= 63,
					type	= "toggle",
					name	= L["Show Spellpower"],
					desc	= L["ADD_SPELL_DMG_MOD_AP"],
					arg	= "GetModList.ADD_SPELL_DMG_MOD_AP",
					hidden	= paladin and shaman,
				},
				armorHeader = {
					order	= 71,
					type	= "header",
					name	= ARMOR,
					hidden	= warrior and deathknight,
				},
				armorAttackPower = {
					order	= 72,
					type	= "toggle",
					name	= L["Show Attack Power"],
					desc	= L["ADD_AP_MOD_ARMOR"],
					arg	= "GetModList.ADD_AP_MOD_ARMOR",
					hidden	= warrior and deathknight,
				},
				regenHeader = {
					order	= 81,
					type	= "header",
					name	= MANA_REGEN,
					hidden	= mana,
				},
				regenReplenish = {
					order	= 82,
					type	= "toggle",
					name	= L["Show Replenish"],
					desc	= "REPLENISH_REGEN_DESC",
					arg	= "stats.replenish",
					hidden	= mana,
				},
			},
		}
	end
	return stats;
end

-----------------------
-- Hit Rating Module --
-----------------------
local hitrating = nil
local function giveHitRating()

	if (not hitrating) then
		hitrating = {
			type = "group",
			name = ECSNAME,
			get = getter,
			set = setter,
			args = {
				meleeHeader = {
					order	= 11,
					type	= "header",
					name	= MELEE,
				},
				displayArmorPen = {
					order	= 12,
					type	= "toggle",
					name	= L["SHOW_ARMORPEN"],
					desc	= L["SHOW_ARMORPEN_DESC"],
					arg	= "hitrating.armorPen",
					width	= "double",
				},
				displayArmorPenLong = {
					order	= 13,
					type	= "toggle",
					name	= L["SHOW_VERBOSE"],
					desc	= L["SHOW_ARMORPEN_LONG_DESC"],
					arg	= "hitrating.armorPenLong",
				},
				--[[
				rangeHeader = {
					order	= 21,
					type	= "header",
					name	= RANGE,
				}, ]]
				spellHeader = {
					order	= 31,
					type	= "header",
					name	= SPELL,
				},
				spellDebuffOn = {
					order	= 32,
					type	= "toggle",
					name	= L["HIT_DEBUFF"],
					desc	= L["HIT_DEBUFF_DESC"],
					arg	= "hitrating.hitDebuff",
				},
				spellHeroicOn = {
					order	= 33,
					type	= "toggle",
					name	= L["HIT_HEROIC"],
					desc	= L["HIT_HEROIC_DESC"],
					arg	= "hitrating.heroicOn",
				},
				displaySpellPen = {
					order	= 34,
					type	= "toggle",
					name	= L["SHOW_SPELLPEN"],
					desc	= L["SHOW_SPELLPEN_DESC"],
					arg	= "hitrating.spellPen",
					width	= "double",
				},
				dispalySpellPenLong = {
					order	= 35,
					type	= "toggle",
					name	= L["SHOW_VERBOSE"],
					desc	= L["SHOW_SPELLPEN_LONG_DESC"],
					arg	= "hitrating.spellPenLong",
				},
			},
		}
	end
	return hitrating;
end

-------------------
-- Options Setup --
-------------------
local function giveProfiles()
	return LibStub("AceDBOptions-3.0"):GetOptionsTable(ecs.db)
end

function ecs:SetupOptions(acedb)
	db = acedb;
	AceConfigReg:RegisterOptionsTable(ECSNAME, fullOptions);
	self.optionsFrame = AceConfigDialog:AddToBlizOptions(ECSNAME, nil, nil, "general");

	-- Fill up our modular options...
	self:RegisterModuleOptions("Stats", giveStats(), "Stats");
	self:RegisterModuleOptions(HIT_RATING, giveHitRating(), HIT_RATING);
	self:RegisterModuleOptions("Profiles", giveProfiles(), "Profiles");

	-- Add in the about panel to the Bliz options
	if LibStub:GetLibrary("LibAboutPanel", true) then
		self.optionsFrame["About"] = LibStub:GetLibrary("LibAboutPanel").new(ECSNAME,"EnhancedCharStats")
	end
end

function ecs:RegisterModuleOptions(name, optionsTable, displayName)
	modularOptions[name] = optionsTable
	self.optionsFrame[name] = AceConfigDialog:AddToBlizOptions(ECSNAME, displayName, ECSNAME, name)
end
